#pragma once

#include <QObject>

#include "discover_server.h"
#include "discover_client.h"
#include "tcp_server.h"
#include "tcp_client.h"

#include <memory>

class LanManager : public QObject
{
	Q_OBJECT

signals:
	void interfaceReady(QObject*);
	void log(const QString&);

public:
	explicit LanManager(QObject* parent = nullptr) :
		discover_server(this),
		discover_client(this)
	{
		connect(&discover_client, &DiscoverClient::timeout, this, &LanManager::discoverTimeout);
		connect(&discover_client, &DiscoverClient::serverFound, this, &LanManager::serverFound);
	}

	virtual ~LanManager() = default;

public:
	DiscoverServer* getDiscoverServer()
	{
		return &discover_server;
	}

	DiscoverClient* getDiscoverClient()
	{
		return &discover_client;
	}

public slots:
	void serverFound(QHostAddress address, quint16 port)
	{
		// stop server discovery
		discover_client.stop();

		m_net = std::make_unique<TcpClient>(address, port);

		emit interfaceReady(m_net.get());
	}

	void clientConnected()
	{
		emit interfaceReady(m_net.get());
	}

	void discoverTimeout()
	{
		emit log("Discovery has timed out...");
		emit log("Switching to server mode");

		discover_client.stop();
		discover_server.start();

		m_net = std::make_unique<TcpServer>();
		connect((TcpServer*)m_net.get(), &TcpServer::clientConnected, this, &LanManager::clientConnected);
	}

	void startConnection()
	{
		emit log("Starting search for QGBoy servers...");

		discover_client.start();
	}

private:
	DiscoverServer discover_server;
	DiscoverClient discover_client;

	// object that provides signals and slots to communicate with a network
	std::unique_ptr<QObject> m_net{ nullptr };
};
